#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pcb.h"
#include "sim.h"
#include "sched0.h"
#include "sched1.h"
#include "sched2.h"
#include "tracereader.h"
#include "io_queue.h"
#include "stats.h"

/* global debug flag */
int debug;

PCB* running;

Event next_event;

static unsigned nextRunningEventTime();

/* Returns the type of event
 * at the time returned by
 * nextEventTime()
 */
Event nextProcessEvent()
{
	return next_event;
}

/* returns the pcb of the event */
PCB* getPCB()
{
	return running;

}

void clearPCB(){
	running = NULL;
	next_event = 0;
}

void setPCB(PCB* new_run, Event e)
{

	running = new_run;
	
	if(running!=NULL) {
		setCompletedSlice(running, 0);
	}
}

/* return min of 
 * IOSTART, TERMSLICE, TERMPROC
 */
unsigned nextProcessEventTime()
{
	if(NULL!=running){
		return nextRunningEventTime();
    }		

	return 0;
}

static unsigned nextRunningEventTime()
{
	unsigned min_clock = 0, tmp_clock = 0;

    /* TERMSLICE */
	min_clock = getTimeSlice(running) - getCompletedSlice(running);
	next_event = TERMSLICE;

	tmp_clock = getCpuTime(running) - getCompletedTime(running); 

	if(tmp_clock <= min_clock){
		/* else implies TERMPROC is sooner 
		 * and TERMPROC has prioirty over TERMSLICE */
		min_clock = tmp_clock;
		next_event = TERMPROC;
	}

	if( getTimeLineSize(running) > 0
		&& getTimeLineValue(running, getCompletedIO(running)) >= getCompletedTime(running) 
		&& getTimeLineSize(running) > getCompletedIO(running)) 
	{
		tmp_clock = getTimeLineValue(running, getCompletedIO(running)) - getCompletedTime(running);

		if( tmp_clock <= min_clock ) {
            /* IOSTART */
           min_clock = tmp_clock;  
		   next_event = IOSTART;
        }
    }

    return min_clock;
}

void incrementRunningProcess(unsigned delta)
{
	if(NULL!=running){
	
	   	setCompletedTime(running, getCompletedTime(running) + delta);
		setCompletedSlice(running, getCompletedSlice(running) + delta);

		/* sanity check */
    	if(getCompletedTime(running) > getCpuTime(running)){
        	fprintf(stderr, "CPU Time exceeded. %s PID:%u CPUTime:%u/%u\n",
            	getName(running),
            	getPid(running),
            	getCompletedTime(running),
            	getCpuTime(running));
				
				printTimeline(running);

            	exit(EXIT_FAILURE);
    	}

	}
}

